/**
 * axios http
 */
import Axios from 'axios'
import qs from 'qs'
import _ from 'lodash'
import {
  Message
} from 'element-ui'

/** axios默认配置 */
let configAxios = {
  // baseURL: '无需配置，由vue自动代理, 见vue.config.js->devServer.proxy'
  baseURL: '/api',
  // Timeout
  timeout: 60 * 1000,
  withCredentials: true
}

/** 会话票据请求头名称 */
const HEADER_TOKEN_NAME = 'DDR-TICKET'
/** 会话票据请求头名称 */
const TOKEN_NAME = 'token'
/** 登录页面 */
// const LOGIN_PAGE = '/login'
/** ajax请求工具实例 */
const axios = Axios.create(configAxios)

/** axios请求拦截器 */
axios.interceptors.request.use(
  config => {
    let token = sessionStorage.getItem(TOKEN_NAME)
    if (_.isString(token)) {
      config.headers[HEADER_TOKEN_NAME] = token
    }
    return config
  },
  error => {
    Promise.reject(error)
  }
)

/** axios响应拦截器 */
axios.interceptors.response.use(
  response => {
    return successCallback(response)
  },
  error => {
    // Do something with response error
    return errorCallback(error)
  }
)

/**
 * 错误回调函数
 * @param {*} error 错误对象
 */
const errorCallback = error => {
  if (error.response) {
    // The request was made and the server responded with a status code
    // that falls out of the range of 2xx
    if (error.response.data.status) {
      // // 未登录
      // if (error.response.data.status === 30001) {
      //   // sessionStorage.clear()
      //   window.location.href = error.response.data.data
      // } else {
      Message({
        message: error.response.data.message,
        type: 'error'
      })
      // }
    } else {
      Message({
        // 服务挂了
        message: '当前服务异常或网络异常, 请稍后再试',
        type: 'error'
      })
    }
  } else if (error.request) {
    // The request was made but no response was received
    // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
    // http.ClientRequest in node.js
    Message({
      // 网络挂了或服务忙（超时未收到响应）
      message: '当前服务忙或网络异常, 请稍后再试',
      type: 'error'
    })
  } else {
    // Something happened in setting up the request that triggered an Error
    Message({
      message: error.message,
      type: 'error'
    })
  }
  return Promise.reject(error)
}

/**
 * 成功回调函数
 * @param {*} response 响应对象
 */
const successCallback = response => {
  if (response.status > 200) {
    return response.data
  }
  if (response.data.status === 0) {
    return response.data
  }
  // if (response.data.status === 2) { // 未授权code
  //   // 由服务端控制的在ajax中进行的redirect跳转，data属性即为跳转的URL
  //   window.location.href = LOGIN_PAGE
  //   return
  // }
  if (response.data.message) {
    Message({
      message: response.data.message,
      type: 'error'
    })
  }
  return Promise.reject(response.data)
}

/**
 * get
 * @param {String} apiUri api uri
 * @param {Object} params 参数
 */
const get = (apiUri, params) => {
  return axios.get(apiUri, params)
}

/**
 * post
 * @param {String} apiUri api uri
 * @param {ObjectOrJsonString} params 请求参数，对象或json字符串
 * @return {Promise} Promise
 */
const post = (apiUri, params) => {
  let _param = _.isString(params) ? params : qs.stringify(params)
  return axios.post(apiUri, _param, {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  })
}
const postJson = (apiUri, params) => {
  // let _param = _.isString(params) ? params : qs.stringify(params)
  return axios.post(apiUri, JSON.stringify(params), {
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    }
  })
}

/**
 * 下载文件
 * 业务代码中的使用示例：
 * this.$http.download('/common/versionUpdate/download', 'filename.pdf', { aa: 'aaasdf', bb: 1 })
 * @param {String} uri 下载地址
 * @param {String} filename 文件名称
 * @param {Object} params 请求参数
 */
const download = (uri, filename, params) => {
  let userAgent = navigator.userAgent.toLowerCase()
  if (userAgent.indexOf('chrome') > -1 || userAgent.indexOf('firefox') > -1) {
    // chrome,firefox
    console.log('downloadGet in chrome')
    downloadSafe(uri, filename, params)
  } else {
    // IE11,...
    console.log('downloadGet in ie')
    downloadGet(uri, params)
  }
}

/**
 * 下载文件，不安全，get方式，无安全标签和token, 文件名称由服务端响应头控制
 * chrome, 360极速, IE11: down OK
 * firefox down failure
 * @param {String} uri 下载地址
 * @param {Object} params 请求参数
 */
const downloadGet = (uri, params) => {
  console.log('downloadGet in')
  return new Promise((resolve, reject) => {
    try {
      console.log('Promise in 1')
      let iframe = document.createElement('iframe')
      iframe.style.display = 'none'
      // iframe.id = 'NJA_FRAME_ID';
      let ps = param2String(params)
      if (uri.indexOf('?') !== -1) {
        uri += '&' + ps
      } else {
        if (ps.indexOf('=') !== -1) {
          uri += '?' + ps
        }
      }
      console.log('Promise in 2', uri)
      iframe.onload = function () {
        // TODO 这下载不调用问题
        console.log('Promise in 3', uri)
        document.body.removeChild(iframe)
      }
      console.log('Promise in 4', uri)
      if (uri.indexOf('http') !== 0) {
        iframe.src = uri
        // iframe.src = 'http://localhost:' + vueConfig.devServer.port + '/api' + uri
        console.log('Promise in 4 1', uri)
        // iframe.src = store.getters.serviceHost + uri
      } else {
        iframe.src = uri
        console.log('Promise in 4 2', uri)
      }
      console.log('Promise in 5', uri)
      setTimeout(() => {
        resolve('ok')
      }, 1000)
      console.log('Promise in 6', uri)
      window.addEventListener('message', function (error) {
        let res = JSON.parse(error.data)
        if (
          res &&
          typeof res === 'object' &&
          'code' in res &&
          res.code !== 20000
        ) {
          reject(res)
        }
      })
      document.body.appendChild(iframe)
    } catch (e) {
    }
  })
}

/**
 * 将get请求参数转为字符串
 * 示例：{a: 'aa', b: 123} => a=aa&b=123
 * @param {Object/String} params get请求参数
 * @returns {String} 参数字符串
 */
const param2String = params => {
  if (typeof params === 'string') {
    return params
  }
  let ret = ''
  for (let it in params) {
    let val = params[it]
    if (
      typeof val === 'object' && //
      (!(val instanceof Array) ||
        (val.length > 0 && typeof val[0] === 'object'))
    ) {
      val = JSON.stringify(val)
    }
    ret += it + '=' + encodeURIComponent(val) + '&'
  }
  if (ret.length > 0) {
    ret = ret.substring(0, ret.length - 1)
  }
  return ret
}

/**
 * 安全下载，post with token
 * firefox down OK need filename
 * chrome down OK need filename
 * 360极速(blink内核) down OK need filename
 * IE11 down failure
 * @param {String} uri 下载地址
 * @param {String} filename 文件名称
 * @param {Object} params 请求参数
 */
const downloadSafe = (uri, filename, params) => {
  axios({
    method: 'post',
    url: uri,
    data: qs.stringify(params),
    // 指定返回服务器返回的数据类型
    responseType: 'blob'
  })
    .then((response) => {
      // 处理返回的文件流
      let blob = response
      let reader = new FileReader()
      // 转换为base64，可以直接放入a标签href
      reader.readAsDataURL(blob)
      reader.onload = function (e) {
        let link = document.createElement('a')
        link.download = filename
        link.href = e.target.result
        document.body.appendChild(link)
        link.click()
        // 释放URL对象
        window.URL.revokeObjectURL(link.href)
        // 删除link对象
        document.body.removeChild(link)
      }
    })
    .catch(err => {
      Message({
        message: '文件下载失败: ' + err,
        type: 'error'
      })
    })
}

// 统一方法输出口
export {
  post,
  postJson,
  get,
  download,
  axios
}
